home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / X11R4 / cmds / X / dix / colormap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-20  |  63.9 KB  |  2,450 lines

  1. /***********************************************************
  2. Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
  3. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Digital or MIT not be
  12. used in advertising or publicity pertaining to distribution of the
  13. software without specific, written prior permission.  
  14.  
  15. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  16. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  17. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  18. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  19. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  20. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21. SOFTWARE.
  22.  
  23. ******************************************************************/
  24.  
  25. /* $XConsortium: colormap.c,v 5.9 90/01/23 13:35:31 rws Exp $ */
  26.  
  27. #include "X.h"
  28. #define NEED_EVENTS
  29. #include "Xproto.h"
  30. #include "misc.h"
  31. #include "dix.h"
  32. #include "colormapst.h"
  33. #include "os.h"
  34. #include "scrnintstr.h"
  35. #include "resource.h"
  36. #include "windowstr.h"
  37.  
  38. extern XID clientErrorValue;
  39.  
  40. static Pixel FindBestPixel();
  41. static void  CopyFree(), FreeCell(), FreePixels(), UpdateColors();
  42. static int   AllComp(), RedComp(), GreenComp(), BlueComp();
  43. static int   AllocDirect(), AllocPseudo(), FreeCo();
  44. static Bool  AllocCP(), AllocShared();
  45. static int   TellNoMap();
  46.  
  47. int   FreeClientPixels();
  48.  
  49. /* GetNextBitsOrBreak(bits, mask, base)  -- 
  50.  * (Suggestion: First read the macro, then read this explanation.
  51.  *
  52.  * Either generate the next value to OR in to a pixel or break out of this
  53.  * while loop 
  54.  *
  55.  * This macro is used when we're trying to generate all 2^n combinations of
  56.  * bits in mask.  What we're doing here is counting in binary, except that
  57.  * the bits we use to count may not be contiguous.  This macro will be
  58.  * called 2^n times, returning a different value in bits each time. Then
  59.  * it will cause us to break out of a surrounding loop. (It will always be
  60.  * called from within a while loop.)
  61.  * On call: mask is the value we want to find all the combinations for
  62.  * base has 1 bit set where the least significant bit of mask is set
  63.  *
  64.  * For example,if mask is 01010, base should be 0010 and we count like this:
  65.  * 00010 (see this isn't so hard), 
  66.  *     then we add base to bits and get 0100. (bits & ~mask) is (0100 & 0100) so
  67.  *      we add that to bits getting (0100 + 0100) =
  68.  * 01000 for our next value.
  69.  *      then we add 0010 to get 
  70.  * 01010 and we're done (easy as 1, 2, 3)
  71.  */
  72. #define GetNextBitsOrBreak(bits, mask, base)    \
  73.         if((bits) == (mask))         \
  74.         break;                 \
  75.         (bits) += (base);             \
  76.         while((bits) & ~(mask))        \
  77.         (bits) += ((bits) & ~(mask));    
  78. /* ID of server as client */
  79. #define SERVER_ID    0
  80.  
  81. typedef struct 
  82. {
  83.     Colormap    mid;
  84.     int        client;
  85.     } colorResource;
  86.  
  87. /* Invariants:
  88.  * refcnt == 0 means entry is empty
  89.  * refcnt > 0 means entry is useable by many clients, so it can't be changed
  90.  * refcnt == AllocPrivate means entry owned by one client only
  91.  * fShared should only be set if refcnt == AllocPrivate, and only in red map
  92.  */
  93.  
  94.  
  95. /* Create and initialize the color map */
  96. int 
  97. CreateColormap (mid, pScreen, pVisual, ppcmap, alloc, client)
  98.     Colormap    mid;        /* resource to use for this colormap */
  99.     ScreenPtr    pScreen;
  100.     VisualPtr    pVisual;
  101.     ColormapPtr    *ppcmap;    
  102.     int        alloc;        /* 1 iff all entries are allocated writeable */
  103.     int        client;
  104. {
  105.     int        class, size;
  106.     unsigned long sizebytes;
  107.     ColormapPtr    pmap;
  108.     register    EntryPtr    pent;
  109.     int        i;
  110.     register    Pixel    *ppix, **pptr;
  111.  
  112.     class = pVisual->class;
  113.     if(!(class & DynamicClass) && (alloc != AllocNone) && (client != SERVER_ID))
  114.     return (BadMatch);
  115.  
  116.     size = pVisual->ColormapEntries;
  117.     sizebytes = (size * sizeof(Entry)) +
  118.         (MAXCLIENTS * sizeof(Pixel *)) +
  119.         (MAXCLIENTS * sizeof(int));
  120.     if ((class | DynamicClass) == DirectColor)
  121.     sizebytes *= 3;
  122.     sizebytes += sizeof(ColormapRec);
  123.     pmap = (ColormapPtr) xalloc(sizebytes);
  124.     if (!pmap)
  125.     return (BadAlloc);
  126.     pmap->red = (EntryPtr)((char *)pmap + sizeof(ColormapRec));    
  127.     sizebytes = size * sizeof(Entry);
  128.     pmap->clientPixelsRed = (Pixel **)((char *)pmap->red + sizebytes);
  129.     pmap->numPixelsRed = (int *)((char *)pmap->clientPixelsRed +
  130.                  (MAXCLIENTS * sizeof(Pixel *)));
  131.     pmap->mid = mid;
  132.     pmap->flags = 0;     /* start out with all flags clear */
  133.     if(mid == pScreen->defColormap)
  134.     pmap->flags |= IsDefault;
  135.     pmap->pScreen = pScreen;
  136.     pmap->pVisual = pVisual;
  137.     pmap->class = class;
  138.     pmap->freeRed = size;
  139.     bzero ((char *) pmap->red, (int)sizebytes);
  140.     bzero((char *) pmap->numPixelsRed, MAXCLIENTS * sizeof(int));
  141.     for (pptr = &pmap->clientPixelsRed[MAXCLIENTS]; --pptr >= pmap->clientPixelsRed; )
  142.     *pptr = (Pixel *)NULL;
  143.     if (alloc == AllocAll)
  144.     {
  145.     pmap->flags |= AllAllocated;
  146.     for (pent = &pmap->red[size - 1]; pent >= pmap->red; pent--)
  147.         pent->refcnt = AllocPrivate;
  148.     pmap->freeRed = 0;
  149.     ppix = (Pixel *)xalloc(size * sizeof(Pixel));
  150.     if (!ppix)
  151.     {
  152.         xfree(pmap);
  153.         return (BadAlloc);
  154.     }
  155.     pmap->clientPixelsRed[client] = ppix;
  156.     for(i = 0; i < size; i++)
  157.         ppix[i] = i;
  158.     pmap->numPixelsRed[client] = size;
  159.     }
  160.  
  161.     if ((class | DynamicClass) == DirectColor)
  162.     {
  163.     pmap->freeGreen = size;
  164.     pmap->green = (EntryPtr)((char *)pmap->numPixelsRed +
  165.                  (MAXCLIENTS * sizeof(int)));
  166.     pmap->clientPixelsGreen = (Pixel **)((char *)pmap->green + sizebytes);
  167.     pmap->numPixelsGreen = (int *)((char *)pmap->clientPixelsGreen +
  168.                        (MAXCLIENTS * sizeof(Pixel *)));
  169.     pmap->freeBlue = size;
  170.     pmap->blue = (EntryPtr)((char *)pmap->numPixelsGreen +
  171.                 (MAXCLIENTS * sizeof(int)));
  172.     pmap->clientPixelsBlue = (Pixel **)((char *)pmap->blue + sizebytes);
  173.     pmap->numPixelsBlue = (int *)((char *)pmap->clientPixelsBlue +
  174.                       (MAXCLIENTS * sizeof(Pixel *)));
  175.  
  176.     bzero ((char *) pmap->green, (int)sizebytes);
  177.     bzero ((char *) pmap->blue, (int)sizebytes);
  178.  
  179.     bcopy((char *) pmap->clientPixelsRed,
  180.           (char *) pmap->clientPixelsGreen,
  181.           MAXCLIENTS * sizeof(Pixel *));
  182.     bcopy((char *) pmap->clientPixelsRed,
  183.           (char *) pmap->clientPixelsBlue,
  184.           MAXCLIENTS * sizeof(Pixel *));
  185.     bzero((char *) pmap->numPixelsGreen, MAXCLIENTS * sizeof(int));
  186.     bzero((char *) pmap->numPixelsBlue, MAXCLIENTS * sizeof(int));
  187.  
  188.     /* If every cell is allocated, mark its refcnt */
  189.     if (alloc == AllocAll)
  190.     {
  191.         for(pent = &pmap->green[size-1]; pent >= pmap->green; pent--)
  192.         pent->refcnt = AllocPrivate;
  193.         for(pent = &pmap->blue[size-1]; pent >= pmap->blue; pent--)
  194.         pent->refcnt = AllocPrivate;
  195.         pmap->freeGreen = 0;
  196.         pmap->freeBlue = 0;
  197.  
  198.         ppix = (Pixel *) xalloc(size * sizeof(Pixel));
  199.         if (!ppix)
  200.         {
  201.         xfree(pmap->clientPixelsRed[client]);
  202.         xfree(pmap);
  203.         return(BadAlloc);
  204.         }
  205.         pmap->clientPixelsGreen[client] = ppix;
  206.         for(i = 0; i < size; i++)
  207.         ppix[i] = i;
  208.         pmap->numPixelsGreen[client] = size;
  209.  
  210.         ppix = (Pixel *) xalloc(size * sizeof(Pixel));
  211.         if (!ppix)
  212.         {
  213.         xfree(pmap->clientPixelsGreen[client]);
  214.         xfree(pmap->clientPixelsRed[client]);
  215.         xfree(pmap);
  216.         return(BadAlloc);
  217.         }
  218.         pmap->clientPixelsBlue[client] = ppix;
  219.  
  220.         for(i = 0; i < size; i++)
  221.         ppix[i] = i;
  222.         pmap->numPixelsBlue[client] = size;
  223.     }
  224.     }
  225.     if (!AddResource(mid, RT_COLORMAP, (pointer)pmap))
  226.     return (BadAlloc);
  227.     /* If the device wants a chance to initialize the colormap in any way,
  228.      * this is it.  In specific, if this is a Static colormap, this is the
  229.      * time to fill in the colormap's values */
  230.     pmap->flags |= BeingCreated;
  231.     if (!(*pScreen->CreateColormap)(pmap))
  232.     {
  233.     FreeColormap(pmap, mid);
  234.     return BadAlloc;
  235.     }
  236.     pmap->flags &= ~BeingCreated;
  237.     *ppcmap = pmap;
  238.     return (Success);
  239. }
  240.  
  241. int
  242. FreeColormap (pmap, mid)
  243.     ColormapPtr    pmap;
  244.     Colormap    mid;
  245. {
  246.     int        i;
  247.     register EntryPtr pent;
  248.  
  249.     if(CLIENT_ID(mid) != SERVER_ID)
  250.     {
  251.         (*pmap->pScreen->UninstallColormap) (pmap);
  252.         WalkTree(pmap->pScreen, TellNoMap, (pointer) &mid);
  253.     }
  254.  
  255.     /* This is the device's chance to undo anything it needs to, especially
  256.      * to free any storage it allocated */
  257.     (*pmap->pScreen->DestroyColormap)(pmap);
  258.  
  259.     if(pmap->clientPixelsRed)
  260.     {
  261.     for(i = 0; i < MAXCLIENTS; i++)
  262.         xfree(pmap->clientPixelsRed[i]);
  263.     }
  264.  
  265.     if ((pmap->class == PseudoColor) || (pmap->class == GrayScale))
  266.     {
  267.     for(pent = &pmap->red[pmap->pVisual->ColormapEntries - 1];
  268.         pent >= pmap->red;
  269.         pent--)
  270.     {
  271.         if(pent->fShared)
  272.         {
  273.         if (--pent->co.shco.red->refcnt == 0)
  274.             xfree(pent->co.shco.red);
  275.         if (--pent->co.shco.green->refcnt == 0)
  276.             xfree(pent->co.shco.green);
  277.         if (--pent->co.shco.blue->refcnt == 0)
  278.             xfree(pent->co.shco.blue);
  279.         }
  280.     }
  281.     }
  282.     if((pmap->class | DynamicClass) == DirectColor)
  283.     {
  284.         for(i = 0; i < MAXCLIENTS; i++)
  285.     {
  286.             xfree(pmap->clientPixelsGreen[i]);
  287.             xfree(pmap->clientPixelsBlue[i]);
  288.         }
  289.     }
  290.     xfree(pmap);
  291.     return(Success);
  292. }
  293.  
  294. /* Tell window that pmid has disappeared */
  295. static int
  296. TellNoMap (pwin, pmid)
  297.     WindowPtr    pwin;
  298.     Colormap     *pmid;
  299. {
  300.     xEvent     xE;
  301.     if (wColormap(pwin) == *pmid)
  302.     {
  303.     /* This should be call to DeliverEvent */
  304.     xE.u.u.type = ColormapNotify;
  305.     xE.u.colormap.window = pwin->drawable.id;
  306.     xE.u.colormap.colormap = None;
  307.     xE.u.colormap.new = TRUE;
  308.     xE.u.colormap.state = ColormapUninstalled;
  309.     DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL);
  310.     if (pwin->optional) {
  311.         pwin->optional->colormap = None;
  312.         CheckWindowOptionalNeed (pwin);
  313.     }
  314.     }
  315.  
  316.     return (WT_WALKCHILDREN);
  317. }
  318.  
  319. /* Tell window that pmid got uninstalled */
  320. int
  321. TellLostMap (pwin, pmid)
  322.     WindowPtr    pwin;
  323.     Colormap     *pmid;
  324. {
  325.     xEvent     xE;
  326.     if (wColormap(pwin) == *pmid)
  327.     {
  328.     /* This should be call to DeliverEvent */
  329.     xE.u.u.type = ColormapNotify;
  330.     xE.u.colormap.window = pwin->drawable.id;
  331.     xE.u.colormap.colormap = *pmid;
  332.     xE.u.colormap.new = FALSE;
  333.     xE.u.colormap.state = ColormapUninstalled;
  334.     DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL);
  335.     }
  336.  
  337.     return (WT_WALKCHILDREN);
  338. }
  339.  
  340. /* Tell window that pmid got installed */
  341. int
  342. TellGainedMap (pwin, pmid)
  343.     WindowPtr    pwin;
  344.     Colormap     *pmid;
  345. {
  346.     xEvent     xE;
  347.     if (wColormap (pwin) == *pmid)
  348.     {
  349.     /* This should be call to DeliverEvent */
  350.     xE.u.u.type = ColormapNotify;
  351.     xE.u.colormap.window = pwin->drawable.id;
  352.     xE.u.colormap.colormap = *pmid;
  353.     xE.u.colormap.new = FALSE;
  354.     xE.u.colormap.state = ColormapInstalled;
  355.     DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL);
  356.     }
  357.  
  358.     return (WT_WALKCHILDREN);
  359. }
  360.  
  361.   
  362. int
  363. CopyColormapAndFree (mid, pSrc, client)
  364.     Colormap    mid;
  365.     ColormapPtr    pSrc;
  366.     int        client;
  367. {
  368.     ColormapPtr    pmap = (ColormapPtr) NULL;
  369.     int        result, alloc, size;
  370.     Colormap    midSrc;
  371.     ScreenPtr    pScreen;
  372.     VisualPtr    pVisual;
  373.  
  374.     pScreen = pSrc->pScreen;
  375.     pVisual = pSrc->pVisual;
  376.     midSrc = pSrc->mid;
  377.     alloc = ((pSrc->flags & AllAllocated) && CLIENT_ID(midSrc) == client) ?
  378.             AllocAll : AllocNone;
  379.     size = pVisual->ColormapEntries;
  380.  
  381.     /* If the create returns non-0, it failed */
  382.     result = CreateColormap (mid, pScreen, pVisual, &pmap, alloc, client);
  383.     if(result != Success)
  384.         return(result);
  385.     if(alloc == AllocAll)
  386.     {
  387.     bcopy((char *)pSrc->red, (char *)pmap->red, size * sizeof(Entry));
  388.     if((pmap->class | DynamicClass) == DirectColor)
  389.     {
  390.         bcopy((char *)pSrc->green, (char *)pmap->green, size * sizeof(Entry));
  391.         bcopy((char *)pSrc->blue, (char *)pmap->blue, size * sizeof(Entry));
  392.     }
  393.     pSrc->flags &= ~AllAllocated;
  394.     FreePixels(pSrc, client);
  395.     UpdateColors(pmap);
  396.     return(Success);
  397.     }
  398.  
  399.     CopyFree(REDMAP, client, pSrc, pmap);
  400.     if ((pmap->class | DynamicClass) == DirectColor)
  401.     {
  402.     CopyFree(GREENMAP, client, pSrc, pmap);
  403.     CopyFree(BLUEMAP, client, pSrc, pmap);
  404.     }
  405.     if (pmap->class & DynamicClass)
  406.     UpdateColors(pmap);
  407.     /* XXX should worry about removing any RT_CMAPENTRY resource */
  408.     return(Success);
  409. }
  410.  
  411. /* Helper routine for freeing large numbers of cells from a map */
  412. static void
  413. CopyFree (channel, client, pmapSrc, pmapDst)
  414.     int        channel, client;
  415.     ColormapPtr    pmapSrc, pmapDst;
  416. {
  417.     int        z, npix, oldFree;
  418.     EntryPtr    pentSrcFirst, pentDstFirst;
  419.     EntryPtr    pentSrc, pentDst;
  420.     Pixel    *ppix;
  421.  
  422.     switch(channel)
  423.     {
  424.       case REDMAP:
  425.     ppix = (pmapSrc->clientPixelsRed)[client];
  426.     npix = (pmapSrc->numPixelsRed)[client];
  427.     pentSrcFirst = pmapSrc->red;
  428.     pentDstFirst = pmapDst->red;
  429.     oldFree = pmapSrc->freeRed;
  430.     break;
  431.       case GREENMAP:
  432.     ppix = (pmapSrc->clientPixelsGreen)[client];
  433.     npix = (pmapSrc->numPixelsGreen)[client];
  434.     pentSrcFirst = pmapSrc->green;
  435.     pentDstFirst = pmapDst->green;
  436.     oldFree = pmapSrc->freeGreen;
  437.     break;
  438.       case BLUEMAP:
  439.     ppix = (pmapSrc->clientPixelsBlue)[client];
  440.     npix = (pmapSrc->numPixelsBlue)[client];
  441.     pentSrcFirst = pmapSrc->blue;
  442.     pentDstFirst = pmapDst->blue;
  443.     oldFree = pmapSrc->freeBlue;
  444.     break;
  445.     }
  446.     if (pmapSrc->class & DynamicClass)
  447.     {
  448.     for(z = npix; --z >= 0; ppix++)
  449.     {
  450.         /* Copy entries */
  451.         pentSrc = pentSrcFirst + *ppix;
  452.         pentDst = pentDstFirst + *ppix;
  453.         if (pentDst->refcnt > 0)
  454.         {
  455.         pentDst->refcnt++;
  456.         }
  457.         else
  458.         {
  459.         *pentDst = *pentSrc;
  460.         if (pentSrc->refcnt > 0)
  461.             pentDst->refcnt = 1;
  462.         else
  463.             pentSrc->fShared = FALSE;
  464.         }
  465.         FreeCell(pmapSrc, *ppix, channel);
  466.     }
  467.     }
  468.  
  469.     /* Note that FreeCell has already fixed pmapSrc->free{Color} */
  470.     switch(channel)
  471.     {
  472.       case REDMAP:
  473.         pmapDst->freeRed -= (pmapSrc->freeRed - oldFree);
  474.         (pmapDst->clientPixelsRed)[client] =
  475.         (pmapSrc->clientPixelsRed)[client];
  476.         (pmapSrc->clientPixelsRed)[client] = (Pixel *) NULL;
  477.         (pmapDst->numPixelsRed)[client] = (pmapSrc->numPixelsRed)[client];
  478.         (pmapSrc->numPixelsRed)[client] = 0;
  479.     break;
  480.       case GREENMAP:
  481.         pmapDst->freeGreen -= (pmapSrc->freeGreen - oldFree);
  482.         (pmapDst->clientPixelsGreen)[client] =
  483.         (pmapSrc->clientPixelsGreen)[client];
  484.         (pmapSrc->clientPixelsGreen)[client] = (Pixel *) NULL;
  485.         (pmapDst->numPixelsGreen)[client] = (pmapSrc->numPixelsGreen)[client];
  486.         (pmapSrc->numPixelsGreen)[client] = 0;
  487.     break;
  488.       case BLUEMAP:
  489.         pmapDst->freeBlue -= (pmapSrc->freeBlue - oldFree);
  490.         pmapDst->clientPixelsBlue[client] = pmapSrc->clientPixelsBlue[client];
  491.         pmapSrc->clientPixelsBlue[client] = (Pixel *) NULL;
  492.         pmapDst->numPixelsBlue[client] = pmapSrc->numPixelsBlue[client];
  493.         pmapSrc->numPixelsBlue[client] = 0;
  494.     break;
  495.     }
  496. }
  497.  
  498. /* Free the ith entry in a color map.  Must handle freeing of
  499.  * colors allocated through AllocColorPlanes */
  500. static void
  501. FreeCell (pmap, i, channel)
  502.     ColormapPtr pmap;
  503.     Pixel i;
  504.     int    channel;
  505. {
  506.     EntryPtr pent;
  507.     int    *pCount;
  508.  
  509.  
  510.     switch (channel)
  511.     {
  512.       case PSEUDOMAP:
  513.       case REDMAP:
  514.           pent = (EntryPtr) &pmap->red[i];
  515.       pCount = &pmap->freeRed;
  516.       break;
  517.       case GREENMAP:
  518.           pent = (EntryPtr) &pmap->green[i];
  519.       pCount = &pmap->freeGreen;
  520.       break;
  521.       case BLUEMAP:
  522.           pent = (EntryPtr) &pmap->blue[i];
  523.       pCount = &pmap->freeBlue;
  524.       break;
  525.     }
  526.     /* If it's not privately allocated and it's not time to free it, just
  527.      * decrement the count */
  528.     if (pent->refcnt > 1)
  529.     pent->refcnt--;
  530.     else
  531.     {
  532.         /* If the color type is shared, find the sharedcolor. If decremented
  533.          * refcnt is 0, free the shared cell. */
  534.         if (pent->fShared)
  535.     {
  536.         if(--pent->co.shco.red->refcnt == 0)
  537.         xfree(pent->co.shco.red);
  538.         if(--pent->co.shco.green->refcnt == 0)
  539.         xfree(pent->co.shco.green);
  540.         if(--pent->co.shco.blue->refcnt == 0)
  541.         xfree(pent->co.shco.blue);
  542.         pent->fShared = FALSE;
  543.     }
  544.     pent->refcnt = 0;
  545.     *pCount += 1;
  546.     }
  547. }
  548.  
  549. static void
  550. UpdateColors (pmap)
  551.     ColormapPtr    pmap;
  552. {
  553.     xColorItem        *defs;
  554.     register xColorItem *pdef;
  555.     register EntryPtr     pent;
  556.     register VisualPtr    pVisual;
  557.     int            i, n, size;
  558.  
  559.     pVisual = pmap->pVisual;
  560.     size = pVisual->ColormapEntries;
  561.     defs = (xColorItem *)ALLOCATE_LOCAL(size * sizeof(xColorItem));
  562.     if (!defs)
  563.     return;
  564.     n = 0;
  565.     pdef = defs;
  566.     if (pmap->class == DirectColor)
  567.     {
  568.         for (i = 0; i < size; i++)
  569.     {
  570.         if (!pmap->red[i].refcnt &&
  571.         !pmap->green[i].refcnt &&
  572.         !pmap->blue[i].refcnt)
  573.         continue;
  574.         pdef->pixel = ((Pixel)i << pVisual->offsetRed) |
  575.               ((Pixel)i << pVisual->offsetGreen) |
  576.               ((Pixel)i << pVisual->offsetBlue);
  577.         pdef->red = pmap->red[i].co.local.red;
  578.         pdef->green = pmap->green[i].co.local.green;
  579.         pdef->blue = pmap->blue[i].co.local.blue;
  580.         pdef++;
  581.         n++;
  582.     }
  583.     }
  584.     else
  585.     {
  586.         for (i = 0, pent = pmap->red; i < size; i++, pent++)
  587.     {
  588.         if (!pent->refcnt)
  589.         continue;
  590.         pdef->pixel = i;
  591.         if(pent->fShared)
  592.         {
  593.         pdef->red = pent->co.shco.red->color;
  594.         pdef->green = pent->co.shco.green->color;
  595.         pdef->blue = pent->co.shco.blue->color;
  596.         }
  597.         else
  598.         {
  599.         pdef->red = pent->co.local.red;
  600.         pdef->green = pent->co.local.green;
  601.         pdef->blue = pent->co.local.blue;
  602.         }
  603.         pdef++;
  604.         n++;
  605.     }
  606.     }
  607.     if (n)
  608.     (*pmap->pScreen->StoreColors)(pmap, n, defs);
  609.     DEALLOCATE_LOCAL(defs);
  610. }
  611.  
  612. /* Get a read-only color from a ColorMap (probably slow for large maps)
  613.  * Returns by changing the value in pred, pgreen, pblue and pPix
  614.  */
  615. int
  616. AllocColor (pmap, pred, pgreen, pblue, pPix, client)
  617.     ColormapPtr        pmap;
  618.     unsigned short     *pred, *pgreen, *pblue;
  619.     Pixel        *pPix;
  620.     int            client;
  621. {
  622.     Pixel    pixR, pixG, pixB;
  623.     int        entries;
  624.     xrgb    rgb;
  625.     int        class;
  626.     VisualPtr    pVisual;
  627.     int        npix;
  628.     Pixel    *ppix;
  629.  
  630.     pVisual = pmap->pVisual;
  631.     (*pmap->pScreen->ResolveColor) (pred, pgreen, pblue, pVisual);
  632.     rgb.red = *pred;
  633.     rgb.green = *pgreen;
  634.     rgb.blue = *pblue;
  635.     class = pmap->class;
  636.     entries = pVisual->ColormapEntries;
  637.  
  638.     /* If the colormap is being created, then we want to be able to change
  639.      * the colormap, even if it's a static type. Otherwise, we'd never be
  640.      * able to initialize static colormaps
  641.      */
  642.     if(pmap->flags & BeingCreated)
  643.     class |= DynamicClass;
  644.  
  645.     /* If this is one of the static storage classes, and we're not initializing
  646.      * it, the best we can do is to find the closest color entry to the
  647.      * requested one and return that.
  648.      */
  649.     switch (class) {
  650.     case StaticColor:
  651.     case StaticGray:
  652.     /* Look up all three components in the same pmap */
  653.     *pPix = pixR = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP);
  654.     *pred = pmap->red[pixR].co.local.red;
  655.     *pgreen = pmap->red[pixR].co.local.green;
  656.     *pblue = pmap->red[pixR].co.local.blue;
  657.     npix = pmap->numPixelsRed[client];
  658.     ppix = (Pixel *) xrealloc(pmap->clientPixelsRed[client],
  659.                   (npix + 1) * sizeof(Pixel));
  660.     if (!ppix)
  661.         return (BadAlloc);
  662.     ppix[npix] = pixR;
  663.     pmap->clientPixelsRed[client] = ppix;
  664.     pmap->numPixelsRed[client]++;
  665.     break;
  666.  
  667.     case TrueColor:
  668.     /* Look up each component in its own map, then OR them together */
  669.     pixR = FindBestPixel(pmap->red, entries, &rgb, REDMAP);
  670.     pixG = FindBestPixel(pmap->green, entries, &rgb, GREENMAP);
  671.     pixB = FindBestPixel(pmap->blue, entries, &rgb, BLUEMAP);
  672.     *pPix = (pixR << pVisual->offsetRed) |
  673.         (pixG << pVisual->offsetGreen) |
  674.         (pixB << pVisual->offsetBlue);
  675.     *pred = pmap->red[pixR].co.local.red;
  676.     *pgreen = pmap->green[pixG].co.local.green;
  677.     *pblue = pmap->blue[pixB].co.local.blue;
  678.     npix = pmap->numPixelsRed[client];
  679.     ppix = (Pixel *) xrealloc(pmap->clientPixelsRed[client],
  680.                   (npix + 1) * sizeof(Pixel));
  681.     if (!ppix)
  682.         return (BadAlloc);
  683.     ppix[npix] = pixR;
  684.     pmap->clientPixelsRed[client] = ppix;
  685.     npix = pmap->numPixelsGreen[client];
  686.     ppix = (Pixel *) xrealloc(pmap->clientPixelsGreen[client],
  687.                   (npix + 1) * sizeof(Pixel));
  688.     if (!ppix)
  689.         return (BadAlloc);
  690.     ppix[npix] = pixG;
  691.     pmap->clientPixelsGreen[client] = ppix;
  692.     npix = pmap->numPixelsBlue[client];
  693.     ppix = (Pixel *) xrealloc(pmap->clientPixelsBlue[client],
  694.                   (npix + 1) * sizeof(Pixel));
  695.     if (!ppix)
  696.         return (BadAlloc);
  697.     ppix[npix] = pixB;
  698.     pmap->clientPixelsBlue[client] = ppix;
  699.     pmap->numPixelsRed[client]++;
  700.     pmap->numPixelsGreen[client]++;
  701.     pmap->numPixelsBlue[client]++;
  702.     break;
  703.  
  704.     case GrayScale:
  705.     case PseudoColor:
  706.     if (FindColor(pmap, pmap->red, entries, &rgb, pPix, PSEUDOMAP,
  707.               client, AllComp) != Success)
  708.         return (BadAlloc);
  709.         break;
  710.  
  711.     case DirectColor:
  712.     pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed; 
  713.     if (FindColor(pmap, pmap->red, entries, &rgb, &pixR, REDMAP,
  714.               client, RedComp) != Success)
  715.         return (BadAlloc);
  716.     pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen; 
  717.     if (FindColor(pmap, pmap->green, entries, &rgb, &pixG, GREENMAP,
  718.               client, GreenComp) != Success)
  719.     {
  720.         (void)FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel)0);
  721.         return (BadAlloc);
  722.     }
  723.     pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue; 
  724.     if (FindColor(pmap, pmap->blue, entries, &rgb, &pixB, BLUEMAP,
  725.               client, BlueComp) != Success)
  726.     {
  727.         (void)FreeCo(pmap, client, GREENMAP, 1, &pixG, (Pixel)0);
  728.         (void)FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel)0);
  729.         return (BadAlloc);
  730.     }
  731.     *pPix = pixR | pixG | pixB;
  732.     break;
  733.     }
  734.  
  735.     /* if this is the client's first pixel in this colormap, tell the
  736.      * resource manager that the client has pixels in this colormap which
  737.      * should be freed when the client dies */
  738.     if ((pmap->numPixelsRed[client] == 1) &&
  739.     (CLIENT_ID(pmap->mid) != client) &&
  740.     !(pmap->flags & BeingCreated))
  741.     {
  742.     colorResource    *pcr;
  743.  
  744.     pcr = (colorResource *) xalloc(sizeof(colorResource));
  745.     if (!pcr)
  746.     {
  747.         (void)FreeColors(pmap, client, 1, pPix, (Pixel)0);
  748.         return (BadAlloc);
  749.     }
  750.     pcr->mid = pmap->mid;
  751.     pcr->client = client;
  752.     if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr))
  753.         return (BadAlloc);
  754.     }
  755.     return (Success);
  756. }
  757.  
  758. #ifndef hpux
  759. /*
  760.  * FakeAllocColor -- fake an AllocColor request by
  761.  * returning a free pixel if availible, otherwise returning
  762.  * the closest matching pixel.  This is used by the mi
  763.  * software sprite code to recolor cursors.  A nice side-effect
  764.  * is that this routine will never return failure.
  765.  */
  766.  
  767. FakeAllocColor (pmap, item)
  768.     register ColormapPtr pmap;
  769.     register xColorItem  *item;
  770. {
  771.     Pixel    pixR, pixG, pixB;
  772.     int        entries;
  773.     xrgb    rgb;
  774.     int        class;
  775.     register VisualPtr    pVisual;
  776.  
  777.     pVisual = pmap->pVisual;
  778.     rgb.red = item->red;
  779.     rgb.green = item->green;
  780.     rgb.blue = item->blue;
  781.     (*pmap->pScreen->ResolveColor) (&rgb.red, &rgb.green, &rgb.blue, pVisual);
  782.     class = pmap->class;
  783.     entries = pVisual->ColormapEntries;
  784.  
  785.     switch (class) {
  786.     case GrayScale:
  787.     case PseudoColor:
  788.     if (FindColor(pmap, pmap->red, entries, &rgb, &item->pixel, PSEUDOMAP,
  789.               -1, AllComp) == Success)
  790.         break;
  791.     /* fall through ... */
  792.     case StaticColor:
  793.     case StaticGray:
  794.     item->pixel = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP);
  795.     break;
  796.  
  797.     case DirectColor:
  798.     /* Look up each component in its own map, then OR them together */
  799.     pixR = (item->pixel & pVisual->redMask) >> pVisual->offsetRed; 
  800.     pixG = (item->pixel & pVisual->greenMask) >> pVisual->offsetGreen; 
  801.     pixB = (item->pixel & pVisual->blueMask) >> pVisual->offsetBlue; 
  802.     if (FindColor(pmap, pmap->red, entries, &rgb, &pixR, REDMAP,
  803.               -1, RedComp) != Success)
  804.         pixR = FindBestPixel(pmap->red, entries, &rgb, REDMAP);
  805.     if (FindColor(pmap, pmap->green, entries, &rgb, &pixG, GREENMAP,
  806.               -1, GreenComp) != Success)
  807.         pixG = FindBestPixel(pmap->green, entries, &rgb, GREENMAP);
  808.     if (FindColor(pmap, pmap->blue, entries, &rgb, &pixB, BLUEMAP,
  809.               -1, BlueComp) != Success)
  810.         pixB = FindBestPixel(pmap->blue, entries, &rgb, BLUEMAP);
  811.     item->pixel = (pixR << pVisual->offsetRed) |
  812.               (pixG << pVisual->offsetGreen) |
  813.               (pixB << pVisual->offsetBlue);
  814.     break;
  815.  
  816.     case TrueColor:
  817.     /* Look up each component in its own map, then OR them together */
  818.     pixR = FindBestPixel(pmap->red, entries, &rgb, REDMAP);
  819.     pixG = FindBestPixel(pmap->green, entries, &rgb, GREENMAP);
  820.     pixB = FindBestPixel(pmap->blue, entries, &rgb, BLUEMAP);
  821.     item->pixel = (pixR << pVisual->offsetRed) |
  822.               (pixG << pVisual->offsetGreen) |
  823.               (pixB << pVisual->offsetBlue);
  824.     break;
  825.     }
  826. }
  827.  
  828. /* free a pixel value obtained from FakeAllocColor */
  829. FakeFreeColor(pmap, pixel)
  830.     register ColormapPtr pmap;
  831.     Pixel pixel;
  832. {
  833.     register VisualPtr pVisual;
  834.     Pixel pixR, pixG, pixB;
  835.  
  836.     switch (pmap->class) {
  837.     case GrayScale:
  838.     case PseudoColor:
  839.     if (pmap->red[pixel].refcnt == AllocTemporary)
  840.         pmap->red[pixel].refcnt = 0;
  841.     break;
  842.     case DirectColor:
  843.     pVisual = pmap->pVisual;
  844.     pixR = (pixel & pVisual->redMask) >> pVisual->offsetRed; 
  845.     pixG = (pixel & pVisual->greenMask) >> pVisual->offsetGreen; 
  846.     pixB = (pixel & pVisual->blueMask) >> pVisual->offsetBlue; 
  847.     if (pmap->red[pixR].refcnt == AllocTemporary)
  848.         pmap->red[pixR].refcnt = 0;
  849.     if (pmap->green[pixG].refcnt == AllocTemporary)
  850.         pmap->green[pixG].refcnt = 0;
  851.     if (pmap->blue[pixB].refcnt == AllocTemporary)
  852.         pmap->blue[pixB].refcnt = 0;
  853.     break;
  854.     }
  855. }
  856. #else
  857. /* XXX for now preserve buggy R4 code for HP ddx binary compatibility */
  858. FakeAllocColor (pmap, pred, pgreen, pblue, pPix, read_only)
  859.     ColormapPtr        pmap;
  860.     unsigned short     *pred, *pgreen, *pblue;
  861.     Pixel        *pPix;
  862.     Bool        *read_only;
  863. {
  864.     Pixel    pixR, pixG, pixB;
  865.     int        entries;
  866.     xrgb    rgb;
  867.     int        class;
  868.     VisualPtr    pVisual;
  869.     static Pixel lastPix = 0;
  870.  
  871.     pVisual = pmap->pVisual;
  872.     (*pmap->pScreen->ResolveColor) (pred, pgreen, pblue, pVisual);
  873.     rgb.red = *pred;
  874.     rgb.green = *pgreen;
  875.     rgb.blue = *pblue;
  876.     class = pmap->class;
  877.     entries = pVisual->ColormapEntries;
  878.     /* kludge to avoid duplicate allocations most of the time */
  879.     lastPix++;
  880.     if (lastPix >= entries)
  881.     lastPix = 0;
  882.     *pPix = lastPix;
  883.     
  884.  
  885.     /* If this is one of the static storage classes, and we're not initializing
  886.      * it, the best we can do is to find the closest color entry to the
  887.      * requested one and return that.
  888.      */
  889.     switch (class) {
  890.     case GrayScale:
  891.     case PseudoColor:
  892.     if (FindColor(pmap, pmap->red, entries, &rgb, pPix, PSEUDOMAP,
  893.               -1, AllComp) == Success)
  894.     {
  895.         break;
  896.     }
  897.     /* fall through ... */
  898.     case StaticColor:
  899.     case StaticGray:
  900.     *pPix = pixR = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP);
  901.     *pred = pmap->red[pixR].co.local.red;
  902.     *pgreen = pmap->red[pixR].co.local.green;
  903.     *pblue = pmap->red[pixR].co.local.blue;
  904.     *read_only = TRUE;
  905.     break;
  906.  
  907.     case DirectColor:
  908.     pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed; 
  909.     pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen; 
  910.     pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue; 
  911.     if (FindColor(pmap, pmap->red, entries, &rgb, &pixR, REDMAP,
  912.               -1, RedComp) == Success &&
  913.         FindColor(pmap, pmap->green, entries, &rgb, &pixG, GREENMAP,
  914.               -1, GreenComp) == Success &&
  915.         FindColor(pmap, pmap->blue, entries, &rgb, &pixB, BLUEMAP,
  916.               -1, BlueComp) == Success)
  917.     {
  918.         break;
  919.     }
  920.     /* fall through ... */
  921.     case TrueColor:
  922.     /* Look up each component in its own map, then OR them together */
  923.     pixR = FindBestPixel(pmap->red, entries, &rgb, REDMAP);
  924.     pixG = FindBestPixel(pmap->green, entries, &rgb, GREENMAP);
  925.     pixB = FindBestPixel(pmap->blue, entries, &rgb, BLUEMAP);
  926.     *pPix = (pixR << pVisual->offsetRed) |
  927.         (pixG << pVisual->offsetGreen) |
  928.         (pixB << pVisual->offsetBlue);
  929.     *pred = pmap->red[pixR].co.local.red;
  930.     *pgreen = pmap->green[pixG].co.local.green;
  931.     *pblue = pmap->blue[pixB].co.local.blue;
  932.     *read_only = TRUE;
  933.     break;
  934.     }
  935. }
  936. #endif
  937.  
  938. static Pixel
  939. FindBestPixel(pentFirst, size, prgb, channel)
  940.     EntryPtr    pentFirst;
  941.     int        size;
  942.     xrgb    *prgb;
  943.     int        channel;
  944. {
  945.     EntryPtr    pent;
  946.     Pixel    pixel, final;
  947.     long    dr, dg, db;
  948.     unsigned long minval, diff, sum;
  949.  
  950.     final = 0;
  951.     minval = ~((Pixel)0);
  952.     /* look for the minimal difference */
  953.     for (pent = pentFirst, pixel = 0; pixel < size; pent++, pixel++)
  954.     {
  955.     dr = dg = db = 0;
  956.     switch(channel)
  957.     {
  958.       case PSEUDOMAP:
  959.           dg = pent->co.local.green - prgb->green;
  960.           db = pent->co.local.blue - prgb->blue;
  961.       case REDMAP:
  962.           dr = pent->co.local.red - prgb->red;
  963.           break;
  964.       case GREENMAP:
  965.           dg = pent->co.local.green - prgb->green;
  966.           break;
  967.       case BLUEMAP:
  968.           db = pent->co.local.blue - prgb->blue;
  969.           break;
  970.     }
  971.     diff = dr * dr;
  972.     sum = diff + dg * dg;
  973.     if (sum < diff)
  974.         continue;
  975.     diff = sum + db * db;
  976.     if ((diff >= sum) && (diff < minval))
  977.     {
  978.         final = pixel;
  979.         minval = diff;
  980.     }
  981.     }
  982.     return(final);
  983. }
  984.  
  985. /* Tries to find a color in pmap that exactly matches the one requested in prgb
  986.  * if it can't it allocates one.
  987.  * Starts looking at pentFirst + *pPixel, so if you want a specific pixel,
  988.  * load *pPixel with that value, otherwise set it to 0
  989.  */
  990. int
  991. FindColor (pmap, pentFirst, size, prgb, pPixel, channel, client, comp)
  992.     ColormapPtr    pmap;
  993.     EntryPtr    pentFirst;
  994.     int        size;
  995.     xrgb    *prgb;
  996.     Pixel    *pPixel;
  997.     int        channel;
  998.     int        client;
  999.     int        (*comp) ();
  1000. {
  1001.     EntryPtr    pent;
  1002.     Bool    foundFree;
  1003.     Pixel    pixel, Free;
  1004.     int        npix, count, *nump;
  1005.     Pixel    **pixp, *ppix;
  1006.     xColorItem    def;
  1007.  
  1008.     foundFree = FALSE;
  1009.  
  1010.     if((pixel = *pPixel) >= size)
  1011.     pixel = 0;
  1012.     /* see if there is a match, and also look for a free entry */
  1013.     for (pent = pentFirst + pixel, count = size; --count >= 0; )
  1014.     {
  1015.         if (pent->refcnt > 0)
  1016.     {
  1017.             if ((*comp) (pent, prgb))
  1018.         {
  1019.                 pent->refcnt++;
  1020.         *pPixel = pixel;
  1021.         switch(channel)
  1022.         {
  1023.           case REDMAP:
  1024.             *pPixel <<= pmap->pVisual->offsetRed;
  1025.           case PSEUDOMAP:
  1026.             break;
  1027.           case GREENMAP:
  1028.             *pPixel <<= pmap->pVisual->offsetGreen;
  1029.             break;
  1030.           case BLUEMAP:
  1031.             *pPixel <<= pmap->pVisual->offsetBlue;
  1032.             break;
  1033.         }
  1034.         goto gotit;
  1035.             }
  1036.         }
  1037.     else if (!foundFree && pent->refcnt == 0)
  1038.     {
  1039.         Free = pixel;
  1040.         foundFree = TRUE;
  1041.         /* If we're initializing the colormap, then we are looking for
  1042.          * the first free cell we can find, not to minimize the number
  1043.          * of entries we use.  So don't look any further. */
  1044.         if(pmap->flags & BeingCreated)
  1045.         break;
  1046.     }
  1047.     pixel++;
  1048.     if(pixel >= size)
  1049.     {
  1050.         pent = pentFirst;
  1051.         pixel = 0;
  1052.     }
  1053.     else
  1054.         pent++;
  1055.     }
  1056.  
  1057.     /* If we got here, we didn't find a match.  If we also didn't find
  1058.      * a free entry, we're out of luck.  Otherwise, we'll usurp a free
  1059.      * entry and fill it in */
  1060.     if (!foundFree)
  1061.     return (BadAlloc);
  1062.     pent = pentFirst + Free;
  1063.     pent->fShared = FALSE;
  1064. #ifndef hpux
  1065.     pent->refcnt = (client >= 0) ? 1 : AllocTemporary;
  1066. #else
  1067.     /* XXX for now preserve buggy R4 code for HP ddx binary compatibility */
  1068.     if (client != -1)
  1069.     pent->refcnt = 1;
  1070. #endif
  1071.  
  1072.     def.flags = 0;
  1073.     switch (channel)
  1074.     {
  1075.       case PSEUDOMAP:
  1076.         pent->co.local.green = prgb->green;
  1077.         pent->co.local.blue = prgb->blue;
  1078.     def.green = prgb->green;
  1079.     def.blue = prgb->blue;
  1080.     def.flags |= DoGreen;
  1081.     def.flags |= DoBlue;
  1082.     /* For PseudoColor we load all three values for the pixel,
  1083.      * but only put it in 1 map, the red one */
  1084.  
  1085.     /* So Fall through */
  1086.       case REDMAP:
  1087.         pent->co.local.red = prgb->red;
  1088.         def.red = prgb->red;
  1089.     def.flags |= DoRed;
  1090.     if (client >= 0)
  1091.         pmap->freeRed--;
  1092.     def.pixel = (channel == PSEUDOMAP) ? Free
  1093.                        : Free << pmap->pVisual->offsetRed;
  1094.     break;
  1095.  
  1096.       case GREENMAP:
  1097.     pent->co.local.green = prgb->green;
  1098.         def.green = prgb->green;
  1099.     def.flags |= DoGreen;
  1100.     if (client >= 0)
  1101.         pmap->freeGreen--;
  1102.     def.pixel = Free << pmap->pVisual->offsetGreen;
  1103.     break;
  1104.  
  1105.       case BLUEMAP:
  1106.     pent->co.local.blue = prgb->blue;
  1107.     def.blue = prgb->blue;
  1108.     def.flags |= DoBlue;
  1109.     if (client >= 0)
  1110.         pmap->freeBlue--;
  1111.     def.pixel = Free << pmap->pVisual->offsetBlue;
  1112.     break;
  1113.     }
  1114.     (*pmap->pScreen->StoreColors) (pmap, 1, &def);
  1115.     pixel = Free;    
  1116.     *pPixel = def.pixel;
  1117.  
  1118. gotit:
  1119.     if (pmap->flags & BeingCreated || client == -1)
  1120.     return(Success);
  1121.     /* Now remember the pixel, for freeing later */
  1122.     switch (channel)
  1123.     {
  1124.       case PSEUDOMAP:
  1125.       case REDMAP:
  1126.     nump = pmap->numPixelsRed;
  1127.     pixp = pmap->clientPixelsRed;
  1128.     break;
  1129.  
  1130.       case GREENMAP:
  1131.     nump = pmap->numPixelsGreen;
  1132.     pixp = pmap->clientPixelsGreen;
  1133.     break;
  1134.  
  1135.       case BLUEMAP:
  1136.     nump = pmap->numPixelsBlue;
  1137.     pixp = pmap->clientPixelsBlue;
  1138.     break;
  1139.     }
  1140.     npix = nump[client];
  1141.     ppix = (Pixel *) xrealloc (pixp[client], (npix + 1) * sizeof(Pixel));
  1142.     if (!ppix)
  1143.     {
  1144.     pent->refcnt--;
  1145.     if (!pent->fShared)
  1146.         switch (channel)
  1147.         {
  1148.           case PSEUDOMAP:
  1149.           case REDMAP:
  1150.         pmap->freeRed++;
  1151.         break;
  1152.           case GREENMAP:
  1153.         pmap->freeGreen++;
  1154.         break;
  1155.           case BLUEMAP:
  1156.         pmap->freeBlue++;
  1157.         break;
  1158.         }
  1159.     return(BadAlloc);
  1160.     }
  1161.     ppix[npix] = pixel;
  1162.     pixp[client] = ppix;
  1163.     nump[client]++;
  1164.  
  1165.     return(Success);
  1166. }
  1167.  
  1168. /* Comparison functions -- passed to FindColor to determine if an
  1169.  * entry is already the color we're looking for or not */
  1170. static int
  1171. AllComp (pent, prgb)
  1172.     EntryPtr    pent;
  1173.     xrgb    *prgb;
  1174. {
  1175.     if((pent->co.local.red == prgb->red) &&
  1176.        (pent->co.local.green == prgb->green) &&
  1177.        (pent->co.local.blue == prgb->blue) )
  1178.        return (1);
  1179.     return (0);
  1180. }
  1181.  
  1182. static int
  1183. RedComp (pent, prgb)
  1184.     EntryPtr    pent;
  1185.     xrgb    *prgb;
  1186. {
  1187.     if (pent->co.local.red == prgb->red) 
  1188.     return (1);
  1189.     return (0);
  1190. }
  1191.  
  1192. static int
  1193. GreenComp (pent, prgb)
  1194.     EntryPtr    pent;
  1195.     xrgb    *prgb;
  1196. {
  1197.     if (pent->co.local.green == prgb->green) 
  1198.     return (1);
  1199.     return (0);
  1200. }
  1201.  
  1202. static int
  1203. BlueComp (pent, prgb)
  1204.     EntryPtr    pent;
  1205.     xrgb    *prgb;
  1206. {
  1207.     if (pent->co.local.blue == prgb->blue) 
  1208.     return (1);
  1209.     return (0);
  1210. }
  1211.  
  1212.  
  1213. /* Read the color value of a cell */
  1214.  
  1215. int
  1216. QueryColors (pmap, count, ppixIn, prgbList)
  1217.     ColormapPtr    pmap;
  1218.     int        count;
  1219.     Pixel    *ppixIn;
  1220.     xrgb    *prgbList;
  1221. {
  1222.     Pixel    *ppix, pixel;
  1223.     xrgb    *prgb;
  1224.     VisualPtr    pVisual;
  1225.     EntryPtr    pent;
  1226.     Pixel    i;
  1227.     int        errVal = Success;
  1228.  
  1229.     pVisual = pmap->pVisual;
  1230.     if ((pmap->class | DynamicClass) == DirectColor)
  1231.     {
  1232.  
  1233.     for( ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++)
  1234.     {
  1235.         pixel = *ppix;
  1236.         i  = (pixel & pVisual->redMask) >> pVisual->offsetRed;
  1237.         if (i >= pVisual->ColormapEntries)
  1238.         {
  1239.         clientErrorValue = pixel;
  1240.         errVal =  BadValue;
  1241.         }
  1242.         else
  1243.         {
  1244.         prgb->red = pmap->red[i].co.local.red;
  1245.  
  1246.  
  1247.         i  = (pixel & pVisual->greenMask) >> pVisual->offsetGreen;
  1248.         if (i >= pVisual->ColormapEntries)
  1249.         {
  1250.             clientErrorValue = pixel;
  1251.             errVal =  BadValue;
  1252.         }
  1253.         else
  1254.         {
  1255.             prgb->green = pmap->green[i].co.local.green;
  1256.  
  1257.             i  = (pixel & pVisual->blueMask) >> pVisual->offsetBlue;
  1258.             if (i >= pVisual->ColormapEntries)
  1259.             {
  1260.             clientErrorValue = pixel;
  1261.             errVal =  BadValue;
  1262.             }
  1263.             else
  1264.             prgb->blue = pmap->blue[i].co.local.blue;
  1265.         }
  1266.         }
  1267.     }
  1268.     }
  1269.     else
  1270.     {
  1271.     for( ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++)
  1272.     {
  1273.         pixel = *ppix;
  1274.         if (pixel >= pVisual->ColormapEntries)
  1275.         {
  1276.         clientErrorValue = pixel;
  1277.         errVal = BadValue;
  1278.         }
  1279.         else
  1280.         {
  1281.         pent = (EntryPtr)&pmap->red[pixel];
  1282.         if (pent->fShared)
  1283.         {
  1284.             prgb->red = pent->co.shco.red->color;
  1285.             prgb->green = pent->co.shco.green->color;
  1286.             prgb->blue = pent->co.shco.blue->color;
  1287.         }
  1288.         else
  1289.         {
  1290.             prgb->red = pent->co.local.red;
  1291.             prgb->green = pent->co.local.green;
  1292.             prgb->blue = pent->co.local.blue;
  1293.         }
  1294.         }
  1295.     }
  1296.     }
  1297.     return (errVal);
  1298. }
  1299.  
  1300. static void
  1301. FreePixels(pmap, client)
  1302.     register ColormapPtr    pmap;
  1303.     register int         client;
  1304. {
  1305.     register Pixel        *ppix, *ppixStart;
  1306.     register int         n;
  1307.     int                class;
  1308.  
  1309.     class = pmap->class;
  1310.     ppixStart = pmap->clientPixelsRed[client];
  1311.     if (class & DynamicClass)
  1312.     for (ppix = ppixStart, n = pmap->numPixelsRed[client]; --n >= 0; )
  1313.         FreeCell(pmap, *ppix++, REDMAP);
  1314.     xfree(ppixStart);
  1315.     pmap->clientPixelsRed[client] = (Pixel *) NULL;
  1316.     pmap->numPixelsRed[client] = 0;
  1317.     if ((class | DynamicClass) == DirectColor) 
  1318.     {
  1319.         ppixStart = pmap->clientPixelsGreen[client];
  1320.     if (class & DynamicClass)
  1321.         for (ppix = ppixStart, n = pmap->numPixelsGreen[client]; --n >= 0;)
  1322.         FreeCell(pmap, *ppix++, GREENMAP);
  1323.     xfree(ppixStart);
  1324.     pmap->clientPixelsGreen[client] = (Pixel *) NULL;
  1325.     pmap->numPixelsGreen[client] = 0;
  1326.  
  1327.         ppixStart = pmap->clientPixelsBlue[client];
  1328.     if (class & DynamicClass)
  1329.         for (ppix = ppixStart, n = pmap->numPixelsBlue[client]; --n >= 0; )
  1330.         FreeCell(pmap, *ppix++, BLUEMAP);
  1331.     xfree(ppixStart);
  1332.     pmap->clientPixelsBlue[client] = (Pixel *) NULL;
  1333.     pmap->numPixelsBlue[client] = 0;
  1334.     }
  1335. }
  1336.  
  1337. /* Free all of a client's colors and cells */
  1338. /*ARGSUSED*/
  1339. int
  1340. FreeClientPixels (pcr, fakeid)
  1341.     colorResource *pcr;
  1342.     XID    fakeid;
  1343. {
  1344.     ColormapPtr pmap;
  1345.  
  1346.     pmap = (ColormapPtr) LookupIDByType(pcr->mid, RT_COLORMAP);
  1347.     if (pmap)
  1348.     FreePixels(pmap, pcr->client);
  1349.     xfree(pcr);
  1350. }
  1351.  
  1352. int
  1353. AllocColorCells (client, pmap, colors, planes, contig, ppix, masks)
  1354.     int        client;
  1355.     ColormapPtr    pmap;
  1356.     int        colors, planes;
  1357.     Bool    contig;
  1358.     Pixel    *ppix;
  1359.     Pixel    *masks;
  1360. {
  1361.     Pixel    rmask, gmask, bmask, *ppixFirst, r, g, b;
  1362.     int        n, class;
  1363.     int        ok;
  1364.     int        oldcount;
  1365.     colorResource *pcr = (colorResource *)NULL;
  1366.  
  1367.     class = pmap->class;
  1368.     if (!(class & DynamicClass))
  1369.     return (BadAlloc); /* Shouldn't try on this type */
  1370.     oldcount = pmap->numPixelsRed[client];
  1371.     if (pmap->class == DirectColor)
  1372.     oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client];
  1373.     if (!oldcount && (CLIENT_ID(pmap->mid) != client))
  1374.     {
  1375.     pcr = (colorResource *) xalloc(sizeof(colorResource));
  1376.     if (!pcr)
  1377.         return (BadAlloc);
  1378.     }
  1379.  
  1380.     if (pmap->class == DirectColor)
  1381.     {
  1382.         ok = AllocDirect (client, pmap, colors, planes, planes, planes,
  1383.               contig, ppix, &rmask, &gmask, &bmask);
  1384.     if(ok == Success)
  1385.     {
  1386.         for (r = g = b = 1, n = planes; --n >= 0; r += r, g += g, b += b)
  1387.         {
  1388.         while(!(rmask & r))
  1389.             r += r;
  1390.         while(!(gmask & g))
  1391.             g += g;
  1392.         while(!(bmask & b))
  1393.             b += b;
  1394.         *masks++ = (r << pmap->pVisual->offsetRed) |
  1395.                (g << pmap->pVisual->offsetGreen) |
  1396.                (b << pmap->pVisual->offsetBlue);
  1397.         }
  1398.     }
  1399.     }
  1400.     else
  1401.     {
  1402.         ok = AllocPseudo (client, pmap, colors, planes, contig, ppix, &rmask,
  1403.               &ppixFirst);
  1404.     if(ok == Success)
  1405.     {
  1406.         for (r = 1, n = planes; --n >= 0; r += r)
  1407.         {
  1408.         while(!(rmask & r))
  1409.             r += r;
  1410.         *masks++ = r;
  1411.         }
  1412.     }
  1413.     }
  1414.  
  1415.     /* if this is the client's first pixels in this colormap, tell the
  1416.      * resource manager that the client has pixels in this colormap which
  1417.      * should be freed when the client dies */
  1418.     if ((ok == Success) && pcr)
  1419.     {
  1420.     pcr->mid = pmap->mid;
  1421.     pcr->client = client;
  1422.     if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr))
  1423.         ok = BadAlloc;
  1424.     } else if (pcr)
  1425.     xfree(pcr);
  1426.  
  1427.     return (ok);
  1428. }
  1429.  
  1430.  
  1431. int
  1432. AllocColorPlanes (client, pmap, colors, r, g, b, contig, pixels,
  1433.           prmask, pgmask, pbmask)
  1434.     int        client;
  1435.     ColormapPtr    pmap;
  1436.     int        colors, r, g, b;
  1437.     Bool    contig;
  1438.     Pixel    *pixels;
  1439.     Pixel    *prmask, *pgmask, *pbmask;
  1440. {
  1441.     int        ok;
  1442.     Pixel    mask, *ppixFirst;
  1443.     register Pixel shift;
  1444.     register int i;
  1445.     int        class;
  1446.     int        oldcount;
  1447.     colorResource *pcr = (colorResource *)NULL;
  1448.  
  1449.     class = pmap->class;
  1450.     if (!(class & DynamicClass))
  1451.     return (BadAlloc); /* Shouldn't try on this type */
  1452.     oldcount = pmap->numPixelsRed[client];
  1453.     if (class == DirectColor)
  1454.     oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client];
  1455.     if (!oldcount && (CLIENT_ID(pmap->mid) != client))
  1456.     {
  1457.     pcr = (colorResource *) xalloc(sizeof(colorResource));
  1458.     if (!pcr)
  1459.         return (BadAlloc);
  1460.     }
  1461.  
  1462.     if (class == DirectColor)
  1463.     {
  1464.         ok = AllocDirect (client, pmap, colors, r, g, b, contig, pixels,
  1465.               prmask, pgmask, pbmask);
  1466.     }
  1467.     else
  1468.     {
  1469.     /* Allocate the proper pixels */
  1470.     /* XXX This is sort of bad, because of contig is set, we force all
  1471.      * r + g + b bits to be contiguous.  Should only force contiguity
  1472.      * per mask 
  1473.      */
  1474.         ok = AllocPseudo (client, pmap, colors, r + g + b, contig, pixels,
  1475.               &mask, &ppixFirst);
  1476.  
  1477.     if(ok == Success)
  1478.     {
  1479.         /* now split that mask into three */
  1480.         *prmask = *pgmask = *pbmask = 0;
  1481.         shift = 1;
  1482.         for (i = r; --i >= 0; shift += shift)
  1483.         {
  1484.         while (!(mask & shift))
  1485.             shift += shift;
  1486.         *prmask |= shift;
  1487.         }
  1488.         for (i = g; --i >= 0; shift += shift)
  1489.         {
  1490.         while (!(mask & shift))
  1491.             shift += shift;
  1492.         *pgmask |= shift;
  1493.         }
  1494.         for (i = b; --i >= 0; shift += shift)
  1495.         {
  1496.         while (!(mask & shift))
  1497.             shift += shift;
  1498.         *pbmask |= shift;
  1499.         }
  1500.  
  1501.         /* set up the shared color cells */
  1502.         if (!AllocShared(pmap, pixels, colors, r, g, b,
  1503.                  *prmask, *pgmask, *pbmask, ppixFirst))
  1504.         {
  1505.         (void)FreeColors(pmap, client, colors, pixels, mask);
  1506.         ok = BadAlloc;
  1507.         }
  1508.     }
  1509.     }
  1510.  
  1511.     /* if this is the client's first pixels in this colormap, tell the
  1512.      * resource manager that the client has pixels in this colormap which
  1513.      * should be freed when the client dies */
  1514.     if ((ok == Success) && pcr)
  1515.     {
  1516.     pcr->mid = pmap->mid;
  1517.     pcr->client = client;
  1518.     if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr))
  1519.         ok = BadAlloc;
  1520.     } else if (pcr)
  1521.     xfree(pcr);
  1522.  
  1523.     return (ok);
  1524. }
  1525.  
  1526. static int
  1527. AllocDirect (client, pmap, c, r, g, b, contig, pixels, prmask, pgmask, pbmask)
  1528.     int        client;
  1529.     ColormapPtr    pmap;
  1530.     int        c, r, g, b;
  1531.     Bool    contig;
  1532.     Pixel    *pixels;
  1533.     Pixel    *prmask, *pgmask, *pbmask;
  1534. {
  1535.     Pixel    *ppixRed, *ppixGreen, *ppixBlue;
  1536.     Pixel    *ppix, *pDst, *p;
  1537.     int        npix, npixR, npixG, npixB;
  1538.     Bool    okR, okG, okB;
  1539.     Pixel    *rpix, *gpix, *bpix;
  1540.  
  1541.     npixR = c << r;
  1542.     npixG = c << g;
  1543.     npixB = c << b;
  1544.     if ((r >= 32) || (g >= 32) || (b >= 32) ||
  1545.     (npixR > pmap->freeRed) || (npixR < c) ||
  1546.     (npixG > pmap->freeGreen) || (npixG < c) ||
  1547.     (npixB > pmap->freeBlue) || (npixB < c))
  1548.     return BadAlloc;
  1549.  
  1550.     /* start out with empty pixels */
  1551.     for(p = pixels; p < pixels + c; p++)
  1552.     *p = 0;
  1553.  
  1554.     ppixRed = (Pixel *)ALLOCATE_LOCAL(npixR * sizeof(Pixel));
  1555.     ppixGreen = (Pixel *)ALLOCATE_LOCAL(npixG * sizeof(Pixel));
  1556.     ppixBlue = (Pixel *)ALLOCATE_LOCAL(npixB * sizeof(Pixel));
  1557.     if (!ppixRed || !ppixGreen || !ppixBlue)
  1558.     {
  1559.     if (ppixBlue) DEALLOCATE_LOCAL(ppixBlue);
  1560.     if (ppixGreen) DEALLOCATE_LOCAL(ppixGreen);
  1561.     if (ppixRed) DEALLOCATE_LOCAL(ppixRed);
  1562.     return(BadAlloc);
  1563.     }
  1564.  
  1565.     okR = AllocCP(pmap, pmap->red, c, r, contig, ppixRed, prmask);
  1566.     okG = AllocCP(pmap, pmap->green, c, g, contig, ppixGreen, pgmask);
  1567.     okB = AllocCP(pmap, pmap->blue, c, b, contig, ppixBlue, pbmask);
  1568.  
  1569.     if (okR && okG && okB)
  1570.     {
  1571.     rpix = (Pixel *) xrealloc(pmap->clientPixelsRed[client],
  1572.                   (pmap->numPixelsRed[client] + (c << r)) *
  1573.                   sizeof(Pixel));
  1574.     if (rpix)
  1575.         pmap->clientPixelsRed[client] = rpix;
  1576.     gpix = (Pixel *) xrealloc(pmap->clientPixelsGreen[client],
  1577.                   (pmap->numPixelsGreen[client] + (c << g)) *
  1578.                   sizeof(Pixel));
  1579.     if (gpix)
  1580.         pmap->clientPixelsGreen[client] = gpix;
  1581.     bpix = (Pixel *) xrealloc(pmap->clientPixelsBlue[client],
  1582.                   (pmap->numPixelsBlue[client] + (c << b)) *
  1583.                   sizeof(Pixel));
  1584.     if (bpix)
  1585.         pmap->clientPixelsBlue[client] = bpix;
  1586.     }
  1587.  
  1588.     if (!okR || !okG || !okB || !rpix || !gpix || !bpix)
  1589.     {
  1590.     if (okR)
  1591.         for(ppix = ppixRed, npix = npixR; --npix >= 0; ppix++)
  1592.         pmap->red[*ppix].refcnt = 0;
  1593.     if (okG)
  1594.         for(ppix = ppixGreen, npix = npixG; --npix >= 0; ppix++)
  1595.         pmap->green[*ppix].refcnt = 0;
  1596.     if (okB)
  1597.         for(ppix = ppixBlue, npix = npixB; --npix >= 0; ppix++)
  1598.         pmap->blue[*ppix].refcnt = 0;
  1599.     DEALLOCATE_LOCAL(ppixBlue);
  1600.     DEALLOCATE_LOCAL(ppixGreen);
  1601.     DEALLOCATE_LOCAL(ppixRed);
  1602.     return(BadAlloc);
  1603.     }
  1604.  
  1605.     *prmask <<= pmap->pVisual->offsetRed;
  1606.     *pgmask <<= pmap->pVisual->offsetGreen;
  1607.     *pbmask <<= pmap->pVisual->offsetBlue;
  1608.  
  1609.     ppix = rpix + pmap->numPixelsRed[client];
  1610.     for (pDst = pixels, p = ppixRed; p < ppixRed + npixR; p++)
  1611.     {
  1612.     *ppix++ = *p;
  1613.     if(p < ppixRed + c)
  1614.         *pDst++ |= *p << pmap->pVisual->offsetRed;
  1615.     }
  1616.     pmap->numPixelsRed[client] += npixR;
  1617.     pmap->freeRed -= npixR;
  1618.  
  1619.     ppix = gpix + pmap->numPixelsGreen[client];
  1620.     for (pDst = pixels, p = ppixGreen; p < ppixGreen + npixG; p++)
  1621.     {
  1622.     *ppix++ = *p;
  1623.     if(p < ppixGreen + c)
  1624.         *pDst++ |= *p << pmap->pVisual->offsetGreen;
  1625.     }
  1626.     pmap->numPixelsGreen[client] += npixG;
  1627.     pmap->freeGreen -= npixG;
  1628.  
  1629.     ppix = bpix + pmap->numPixelsBlue[client];
  1630.     for (pDst = pixels, p = ppixBlue; p < ppixBlue + npixB; p++)
  1631.     {
  1632.     *ppix++ = *p;
  1633.     if(p < ppixBlue + c)
  1634.         *pDst++ |= *p << pmap->pVisual->offsetBlue;
  1635.     }
  1636.     pmap->numPixelsBlue[client] += npixB;
  1637.     pmap->freeBlue -= npixB;
  1638.  
  1639.     DEALLOCATE_LOCAL(ppixBlue);
  1640.     DEALLOCATE_LOCAL(ppixGreen);
  1641.     DEALLOCATE_LOCAL(ppixRed);
  1642.  
  1643.     return (Success);
  1644. }
  1645.  
  1646. static int
  1647. AllocPseudo (client, pmap, c, r, contig, pixels, pmask, pppixFirst)
  1648.     int        client;
  1649.     ColormapPtr    pmap;
  1650.     int        c, r;
  1651.     Bool    contig;
  1652.     Pixel    *pixels;
  1653.     Pixel    *pmask;
  1654.     Pixel    **pppixFirst;
  1655. {
  1656.     Pixel    *ppix, *p, *pDst, *ppixTemp;
  1657.     int        npix;
  1658.     Bool    ok;
  1659.  
  1660.     npix = c << r;
  1661.     if ((r >= 32) || (npix > pmap->freeRed) || (npix < c))
  1662.     return(BadAlloc);
  1663.     if(!(ppixTemp = (Pixel *)ALLOCATE_LOCAL(npix * sizeof(Pixel))))
  1664.     return(BadAlloc);
  1665.     ok = AllocCP(pmap, pmap->red, c, r, contig, ppixTemp, pmask);
  1666.  
  1667.     if (ok)
  1668.     {
  1669.  
  1670.     /* all the allocated pixels are added to the client pixel list,
  1671.      * but only the unique ones are returned to the client */
  1672.     ppix = (Pixel *)xrealloc(pmap->clientPixelsRed[client],
  1673.              (pmap->numPixelsRed[client] + npix) * sizeof(Pixel));
  1674.     if (!ppix)
  1675.     {
  1676.         for (p = ppixTemp; p < ppixTemp + npix; p++)
  1677.         pmap->red[*p].refcnt = 0;
  1678.         return (BadAlloc);
  1679.     }
  1680.     pmap->clientPixelsRed[client] = ppix;
  1681.     ppix += pmap->numPixelsRed[client];
  1682.     *pppixFirst = ppix;
  1683.     pDst = pixels;
  1684.     for (p = ppixTemp; p < ppixTemp + npix; p++)
  1685.     {
  1686.         *ppix++ = *p;
  1687.         if(p < ppixTemp + c)
  1688.             *pDst++ = *p;
  1689.     }
  1690.     pmap->numPixelsRed[client] += npix;
  1691.     pmap->freeRed -= npix;
  1692.     }
  1693.     DEALLOCATE_LOCAL(ppixTemp);
  1694.     return (ok ? Success : BadAlloc);
  1695. }
  1696.  
  1697. /* Allocates count << planes pixels from colormap pmap for client. If
  1698.  * contig, then the plane mask is made of consecutive bits.  Returns
  1699.  * all count << pixels in the array pixels. The first count of those
  1700.  * pixels are the unique pixels.  *pMask has the mask to Or with the
  1701.  * unique pixels to get the rest of them.
  1702.  *
  1703.  * Returns True iff all pixels could be allocated 
  1704.  * All cells allocated will have refcnt set to AllocPrivate and shared to FALSE
  1705.  * (see AllocShared for why we care)
  1706.  */
  1707. static Bool
  1708. AllocCP (pmap, pentFirst, count, planes, contig, pixels, pMask)
  1709.     ColormapPtr    pmap;
  1710.     EntryPtr    pentFirst;
  1711.     int        count, planes;
  1712.     Bool    contig;
  1713.     Pixel    *pixels, *pMask;
  1714.     
  1715. {
  1716.     EntryPtr    ent;
  1717.     Pixel    pixel, base, entries, maxp, save;
  1718.     int        dplanes, found;
  1719.     Pixel    *ppix;
  1720.     Pixel    mask;
  1721.     Pixel    finalmask;
  1722.  
  1723.     dplanes = pmap->pVisual->nplanes;
  1724.  
  1725.     /* Easy case.  Allocate pixels only */
  1726.     if (planes == 0)
  1727.     {
  1728.         /* allocate writable entries */
  1729.     ppix = pixels;
  1730.         ent = pentFirst;
  1731.         pixel = 0;
  1732.         while (--count >= 0)
  1733.     {
  1734.             /* Just find count unallocated cells */
  1735.             while (ent->refcnt)
  1736.         {
  1737.                 ent++;
  1738.                 pixel++;
  1739.             }
  1740.             ent->refcnt = AllocPrivate;
  1741.             *ppix++ = pixel;
  1742.         ent->fShared = FALSE;
  1743.         }
  1744.         *pMask = 0;
  1745.         return (TRUE);
  1746.     }
  1747.     else if (planes > dplanes)
  1748.     {
  1749.     return (FALSE);
  1750.     }
  1751.  
  1752.     /* General case count pixels * 2 ^ planes cells to be allocated */
  1753.  
  1754.     /* make room for new pixels */
  1755.     ent = pentFirst;
  1756.  
  1757.     /* first try for contiguous planes, since it's fastest */
  1758.     for (mask = (((Pixel)1) << planes) - 1, base = 1, dplanes -= (planes - 1);
  1759.          --dplanes >= 0;
  1760.          mask += mask, base += base)
  1761.     {
  1762.         ppix = pixels;
  1763.         found = 0;
  1764.         pixel = 0;
  1765.         entries = pmap->pVisual->ColormapEntries - mask;
  1766.         while (pixel < entries)
  1767.     {
  1768.             save = pixel;
  1769.             maxp = pixel + mask + base;
  1770.             /* check if all are free */
  1771.             while (pixel != maxp && ent[pixel].refcnt == 0)
  1772.                 pixel += base;
  1773.         if (pixel == maxp)
  1774.         {
  1775.             /* this one works */
  1776.             *ppix++ = save;
  1777.             found++;
  1778.             if (found == count)
  1779.             {
  1780.             /* found enough, allocate them all */
  1781.             while (--count >= 0)
  1782.             {
  1783.                 pixel = pixels[count];
  1784.                 maxp = pixel + mask;
  1785.                 while (1)
  1786.                 {
  1787.                 ent[pixel].refcnt = AllocPrivate;
  1788.                 ent[pixel].fShared = FALSE;
  1789.                 if (pixel == maxp)
  1790.                     break;
  1791.                 pixel += base;
  1792.                 *ppix++ = pixel;
  1793.                 }
  1794.             }
  1795.             *pMask = mask;
  1796.             return (TRUE);
  1797.             }
  1798.         }
  1799.             pixel = save + 1;
  1800.             if (pixel & mask)
  1801.                 pixel += mask;
  1802.         }
  1803.     }
  1804.  
  1805.     dplanes = pmap->pVisual->nplanes;
  1806.     if (contig || planes == 1 || dplanes < 3)
  1807.     return (FALSE);
  1808.  
  1809.     /* this will be very slow for large maps, need a better algorithm */
  1810.  
  1811.     /*
  1812.        we can generate the smallest and largest numbers that fits in dplanes
  1813.        bits and contain exactly planes bits set as follows. First, we need to
  1814.        check that it is possible to generate such a mask at all.
  1815.        (Non-contiguous masks need one more bit than contiguous masks). Then
  1816.        the smallest such mask consists of the rightmost planes-1 bits set, then
  1817.        a zero, then a one in position planes + 1. The formula is
  1818.          (3 << (planes-1)) -1
  1819.        The largest such masks consists of the leftmost planes-1 bits set, then
  1820.        a zero, then a one bit in position dplanes-planes-1. If dplanes is
  1821.        smaller than 32 (the number of bits in a word) then the formula is:
  1822.          (1<<dplanes) - (1<<(dplanes-planes+1) + (1<<dplanes-planes-1)
  1823.        If dplanes = 32, then we can't calculate (1<<dplanes) and we have
  1824.        to use:
  1825.          ( (1<<(planes-1)) - 1) << (dplanes-planes+1) + (1<<(dplanes-planes-1))
  1826.       
  1827.       << Thank you, Loretta>>>
  1828.  
  1829.     */
  1830.  
  1831.     finalmask =
  1832.         (((((Pixel)1)<<(planes-1)) - 1) << (dplanes-planes+1)) +
  1833.       (((Pixel)1)<<(dplanes-planes-1));
  1834.     for (mask = (((Pixel)3) << (planes -1)) - 1; mask <= finalmask; mask++)
  1835.     {
  1836.         /* next 3 magic statements count number of ones (HAKMEM #169) */
  1837.         pixel = (mask >> 1) & 033333333333;
  1838.         pixel = mask - pixel - ((pixel >> 1) & 033333333333);
  1839.         if ((((pixel + (pixel >> 3)) & 030707070707) % 077) != planes)
  1840.             continue;
  1841.         ppix = pixels;
  1842.         found = 0;
  1843.         entries = pmap->pVisual->ColormapEntries - mask;
  1844.         base = lowbit (mask);
  1845.         for (pixel = 0; pixel < entries; pixel++)
  1846.     {
  1847.         if (pixel & mask)
  1848.             continue;
  1849.         maxp = 0;
  1850.         /* check if all are free */
  1851.         while (ent[pixel + maxp].refcnt == 0)
  1852.         {
  1853.         GetNextBitsOrBreak(maxp, mask, base);
  1854.         }
  1855.         if ((maxp < mask) || (ent[pixel + mask].refcnt != 0))
  1856.         continue;
  1857.         /* this one works */
  1858.         *ppix++ = pixel;
  1859.         found++;
  1860.         if (found < count)
  1861.         continue;
  1862.         /* found enough, allocate them all */
  1863.         while (--count >= 0)
  1864.         {
  1865.         pixel = (pixels)[count];
  1866.         maxp = 0;
  1867.         while (1)
  1868.         {
  1869.             ent[pixel + maxp].refcnt = AllocPrivate;
  1870.             ent[pixel + maxp].fShared = FALSE;
  1871.             GetNextBitsOrBreak(maxp, mask, base);
  1872.             *ppix++ = pixel + maxp;
  1873.         }
  1874.         }
  1875.  
  1876.         *pMask = mask;
  1877.         return (TRUE);
  1878.     }
  1879.     }
  1880.     return (FALSE);
  1881. }
  1882.  
  1883. static Bool
  1884. AllocShared (pmap, ppix, c, r, g, b, rmask, gmask, bmask, ppixFirst)
  1885.     ColormapPtr    pmap;
  1886.     Pixel    *ppix;
  1887.     int        c, r, g, b;
  1888.     Pixel    rmask, gmask, bmask;
  1889.     Pixel    *ppixFirst;    /* First of the client's new pixels */
  1890. {
  1891.     Pixel    *pptr, *cptr;
  1892.     Pixel    basemask;    /* bits not used in any mask */
  1893.     int        npix, z, npixClientNew;
  1894.     Pixel    base, bits;
  1895.     SHAREDCOLOR *pshared, **ppshared, **psharedList;
  1896.  
  1897.     basemask = ~(rmask | gmask | bmask);
  1898.     npixClientNew = c << (r + g + b);
  1899.     psharedList = (SHAREDCOLOR **)ALLOCATE_LOCAL(npixClientNew *
  1900.                          sizeof(SHAREDCOLOR *));
  1901.     if (!psharedList)
  1902.     return FALSE;
  1903.     ppshared = psharedList;
  1904.     for (z = npixClientNew; --z >= 0; )
  1905.     {
  1906.     if (!(ppshared[z] = (SHAREDCOLOR *)xalloc(sizeof(SHAREDCOLOR))))
  1907.     {
  1908.         for (z++ ; z < npixClientNew; z++)
  1909.         xfree(ppshared[z]);
  1910.         return FALSE;
  1911.     }
  1912.     }
  1913.     for(pptr = ppix, npix = c; --npix >= 0; pptr++)
  1914.     {
  1915.     if (rmask)
  1916.     {
  1917.         bits = 0;
  1918.         base = lowbit (rmask);
  1919.         while(1)
  1920.         {
  1921.         pshared = *ppshared++;
  1922.         pshared->refcnt = 1 << (g + b);
  1923.         for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
  1924.         {
  1925.             if (((*cptr & basemask) == ((*pptr | bits) & basemask)) &&
  1926.             ((*cptr & rmask) == ((*pptr | bits) & rmask)))
  1927.             {
  1928.             pmap->red[*cptr].fShared = TRUE;
  1929.             pmap->red[*cptr].co.shco.red = pshared;
  1930.             }
  1931.         }
  1932.         GetNextBitsOrBreak(bits, rmask, base);
  1933.         }
  1934.     }
  1935.     if (gmask)
  1936.     {
  1937.         bits = 0;
  1938.         base = lowbit (gmask);
  1939.         while(1)
  1940.         {
  1941.         pshared = *ppshared++;
  1942.         pshared->refcnt = 1 << (r + b);
  1943.         for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
  1944.         {
  1945.             if (((*cptr & basemask) == ((*pptr | bits) & basemask)) &&
  1946.             ((*cptr & gmask) == ((*pptr | bits) & gmask)))
  1947.             {
  1948.             pmap->red[*cptr].co.shco.green = pshared;
  1949.             }
  1950.         }
  1951.         GetNextBitsOrBreak(bits, gmask, base);
  1952.         }
  1953.     }
  1954.     if (bmask)
  1955.     {
  1956.         bits = 0;
  1957.         base = lowbit (bmask);
  1958.         while(1)
  1959.         {
  1960.         pshared = *ppshared++;
  1961.         pshared->refcnt = 1 << (r + g);
  1962.         for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
  1963.         {
  1964.             if (((*cptr & basemask) == ((*pptr | bits) & basemask)) &&
  1965.             ((*cptr & bmask) == ((*pptr | bits) & bmask)))
  1966.             {
  1967.             pmap->red[*cptr].co.shco.blue = pshared;
  1968.             }
  1969.         }
  1970.         GetNextBitsOrBreak(bits, bmask, base);
  1971.         }
  1972.     }
  1973.     }
  1974.     DEALLOCATE_LOCAL(psharedList);
  1975.     return TRUE;
  1976. }
  1977.  
  1978.  
  1979. /* Free colors and/or cells (probably slow for large numbers) */
  1980.  
  1981. int
  1982. FreeColors (pmap, client, count, pixels, mask)
  1983.     ColormapPtr    pmap;
  1984.     int        client, count;
  1985.     Pixel    *pixels;
  1986.     Pixel    mask;
  1987. {
  1988.     int        rval, result, class;
  1989.     Pixel    rmask;
  1990.  
  1991.     class = pmap->class;
  1992.     if (pmap->flags & AllAllocated)
  1993.     return(BadAccess);
  1994.     if ((class | DynamicClass) == DirectColor)
  1995.     {
  1996.     rmask = mask & (pmap->pVisual->redMask |
  1997.             pmap->pVisual->greenMask |
  1998.             pmap->pVisual->blueMask);
  1999.         result = FreeCo(pmap, client, REDMAP, count, pixels, rmask);
  2000.     /* If any of the three calls fails, we must report that, if more
  2001.      * than one fails, it's ok that we report the last one */
  2002.         rval = FreeCo(pmap, client, GREENMAP, count, pixels, rmask);
  2003.     if(rval != Success)
  2004.         result = rval;
  2005.     rval = FreeCo(pmap, client, BLUEMAP, count, pixels, rmask);
  2006.     if(rval != Success)
  2007.         result = rval;
  2008.     }
  2009.     else
  2010.     {
  2011.     rmask = mask & ((((Pixel)1) << pmap->pVisual->nplanes) - 1);
  2012.         result = FreeCo(pmap, client, PSEUDOMAP, count, pixels, rmask);
  2013.     }
  2014.     if ((mask != rmask) && count)
  2015.     {
  2016.     clientErrorValue = *pixels | mask;
  2017.     result = BadValue;
  2018.     }
  2019.     /* XXX should worry about removing any RT_CMAPENTRY resource */
  2020.     return (result);
  2021. }
  2022.  
  2023. /* Helper for FreeColors -- frees all combinations of *newpixels and mask bits
  2024.  * which the client has allocated in channel colormap cells of pmap.
  2025.  * doesn't change newpixels if it doesn't need to */
  2026. static int
  2027. FreeCo (pmap, client, color, npixIn, ppixIn, mask)
  2028.     ColormapPtr    pmap;        /* which colormap head */
  2029.     int        client;        
  2030.     int        color;        /* which sub-map, eg RED, BLUE, PSEUDO */
  2031.     int        npixIn;        /* number of pixels passed in */
  2032.     Pixel    *ppixIn;    /* list of base pixels */
  2033.     Pixel    mask;        /* mask client gave us */ 
  2034. {
  2035.  
  2036.     Pixel    *ppixClient, pixTest;
  2037.     int        npixClient, npixNew, npix;
  2038.     Pixel    bits, base, cmask;
  2039.     Pixel    *pptr, *cptr;
  2040.     int     n, zapped;
  2041.     int        errVal = Success;
  2042.     int        offset;
  2043.  
  2044.     if (npixIn == 0)
  2045.         return (errVal);
  2046.     bits = 0;
  2047.     zapped = 0;
  2048.     base = lowbit (mask);
  2049.  
  2050.     switch(color)
  2051.     {
  2052.       case REDMAP:
  2053.     cmask = pmap->pVisual->redMask;
  2054.     offset = pmap->pVisual->offsetRed;
  2055.     ppixClient = pmap->clientPixelsRed[client];
  2056.     npixClient = pmap->numPixelsRed[client];
  2057.     break;
  2058.       case GREENMAP:
  2059.     cmask = pmap->pVisual->greenMask;
  2060.     offset = pmap->pVisual->offsetGreen;
  2061.     ppixClient = pmap->clientPixelsGreen[client];
  2062.     npixClient = pmap->numPixelsGreen[client];
  2063.     break;
  2064.       case BLUEMAP:
  2065.     cmask = pmap->pVisual->blueMask;
  2066.     offset = pmap->pVisual->offsetBlue;
  2067.     ppixClient = pmap->clientPixelsBlue[client];
  2068.     npixClient = pmap->numPixelsBlue[client];
  2069.     break;
  2070.       case PSEUDOMAP:
  2071.     cmask = ~((Pixel)0);
  2072.     offset = 0;
  2073.     ppixClient = pmap->clientPixelsRed[client];
  2074.     npixClient = pmap->numPixelsRed[client];
  2075.     break;
  2076.     }
  2077.  
  2078.     /* zap all pixels which match */
  2079.     while (1)
  2080.     {
  2081.         /* go through pixel list */
  2082.         for (pptr = ppixIn, n = npixIn; --n >= 0; pptr++)
  2083.     {
  2084.         pixTest = ((*pptr | bits) & cmask) >> offset;
  2085.         if (pixTest >= pmap->pVisual->ColormapEntries)
  2086.         {
  2087.         clientErrorValue = *pptr | bits;
  2088.         errVal = BadValue;
  2089.         continue;
  2090.         }
  2091.  
  2092.         /* find match in client list */
  2093.         for (cptr = ppixClient, npix = npixClient;
  2094.              --npix >= 0 && *cptr != pixTest;
  2095.          cptr++) ;
  2096.  
  2097.         if (npix >= 0)
  2098.         {
  2099.         if (pmap->class & DynamicClass)
  2100.             FreeCell(pmap, pixTest, color);
  2101.         *cptr = ~((Pixel)0);
  2102.         zapped++;
  2103.         }
  2104.         else
  2105.         errVal = BadAccess;
  2106.     }
  2107.         /* generate next bits value */
  2108.     GetNextBitsOrBreak(bits, mask, base);
  2109.     }
  2110.  
  2111.     /* delete freed pixels from client pixel list */
  2112.     if (zapped)
  2113.     {
  2114.         npixNew = npixClient - zapped;
  2115.         if (npixNew)
  2116.     {
  2117.         /* Since the list can only get smaller, we can do a copy in
  2118.          * place and then realloc to a smaller size */
  2119.             pptr = cptr = ppixClient;
  2120.  
  2121.         /* If we have all the new pixels, we don't have to examine the
  2122.          * rest of the old ones */
  2123.         for(npix = 0; npix < npixNew; cptr++)
  2124.         {
  2125.                 if (*cptr != ~((Pixel)0))
  2126.         {
  2127.                 *pptr++ = *cptr;
  2128.             npix++;
  2129.                 }
  2130.             }
  2131.         pptr = (Pixel *)xrealloc(ppixClient, npixNew * sizeof(Pixel));
  2132.         if (pptr)
  2133.         ppixClient = pptr;
  2134.         npixClient = npixNew;
  2135.         }
  2136.     else
  2137.     {
  2138.         npixClient = 0;
  2139.         xfree(ppixClient);
  2140.             ppixClient = (Pixel *)NULL;
  2141.     }
  2142.     switch(color)
  2143.     {
  2144.       case PSEUDOMAP:
  2145.       case REDMAP:
  2146.         pmap->clientPixelsRed[client] = ppixClient;
  2147.         pmap->numPixelsRed[client] = npixClient;
  2148.         break;
  2149.       case GREENMAP:
  2150.         pmap->clientPixelsGreen[client] = ppixClient;
  2151.         pmap->numPixelsGreen[client] = npixClient;
  2152.         break;
  2153.       case BLUEMAP:
  2154.         pmap->clientPixelsBlue[client] = ppixClient;
  2155.         pmap->numPixelsBlue[client] = npixClient;
  2156.         break;
  2157.     }
  2158.     }
  2159.     return (errVal);
  2160. }
  2161.  
  2162.  
  2163.  
  2164. /* Redefine color values */
  2165. int
  2166. StoreColors (pmap, count, defs)
  2167.     ColormapPtr    pmap;
  2168.     int        count;
  2169.     xColorItem    *defs;
  2170. {
  2171.     register Pixel     pix;
  2172.     register xColorItem *pdef;
  2173.     register EntryPtr     pent, pentT, pentLast;
  2174.     register VisualPtr    pVisual;
  2175.     SHAREDCOLOR        *pred, *pgreen, *pblue;
  2176.     int            n, ChgRed, ChgGreen, ChgBlue, idef;
  2177.     int            class, errVal = Success;
  2178.     int            ok;
  2179.  
  2180.  
  2181.     class = pmap->class;
  2182.     if(!(class & DynamicClass) && !(pmap->flags & BeingCreated))
  2183.     {
  2184.     return(BadAccess);
  2185.     }
  2186.     pVisual = pmap->pVisual;
  2187.  
  2188.     idef = 0;
  2189.     if((class | DynamicClass) == DirectColor)
  2190.     {
  2191.         for (pdef = defs, n = 0; n < count; pdef++, n++)
  2192.     {
  2193.         ok = TRUE;
  2194.             (*pmap->pScreen->ResolveColor)
  2195.             (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual);
  2196.  
  2197.         pix = (pdef->pixel & pVisual->redMask) >> pVisual->offsetRed;
  2198.         if (pix >= pVisual->ColormapEntries )
  2199.         {
  2200.         clientErrorValue = pdef->pixel;
  2201.         errVal = BadValue;
  2202.         ok = FALSE;
  2203.         }
  2204.         else if (pmap->red[pix].refcnt != AllocPrivate)
  2205.         {
  2206.         errVal = BadAccess;
  2207.         ok = FALSE;
  2208.         }
  2209.         else if (pdef->flags & DoRed)
  2210.         {
  2211.         pmap->red[pix].co.local.red = pdef->red;
  2212.         }
  2213.         else
  2214.         {
  2215.         pdef->red = pmap->red[pix].co.local.red;
  2216.         }
  2217.  
  2218.         pix = (pdef->pixel & pVisual->greenMask) >> pVisual->offsetGreen;
  2219.         if (pix >= pVisual->ColormapEntries )
  2220.         {
  2221.         clientErrorValue = pdef->pixel;
  2222.         errVal = BadValue;
  2223.         ok = FALSE;
  2224.         }
  2225.         else if (pmap->green[pix].refcnt != AllocPrivate)
  2226.         {
  2227.         errVal = BadAccess;
  2228.         ok = FALSE;
  2229.         }
  2230.         else if (pdef->flags & DoGreen)
  2231.         {
  2232.         pmap->green[pix].co.local.green = pdef->green;
  2233.         }
  2234.         else
  2235.         {
  2236.         pdef->green = pmap->green[pix].co.local.green;
  2237.         }
  2238.  
  2239.         pix = (pdef->pixel & pVisual->blueMask) >> pVisual->offsetBlue;
  2240.         if (pix >= pVisual->ColormapEntries )
  2241.         {
  2242.         clientErrorValue = pdef->pixel;
  2243.         errVal = BadValue;
  2244.         ok = FALSE;
  2245.         }
  2246.         else if (pmap->blue[pix].refcnt != AllocPrivate)
  2247.         {
  2248.         errVal = BadAccess;
  2249.         ok = FALSE;
  2250.         }
  2251.         else if (pdef->flags & DoBlue)
  2252.         {
  2253.         pmap->blue[pix].co.local.blue = pdef->blue;
  2254.         }
  2255.         else
  2256.         {
  2257.         pdef->blue = pmap->blue[pix].co.local.blue;
  2258.         }
  2259.         /* If this is an o.k. entry, then it gets added to the list
  2260.          * to be sent to the hardware.  If not, skip it.  Once we've
  2261.          * skipped one, we have to copy all the others.
  2262.          */
  2263.         if(ok)
  2264.         {
  2265.         if(idef != n)
  2266.             defs[idef] = defs[n];
  2267.         idef++;
  2268.         }
  2269.     }
  2270.     }
  2271.     else
  2272.     {
  2273.         for (pdef = defs, n = 0; n < count; pdef++, n++)
  2274.     {
  2275.  
  2276.         ok = TRUE;
  2277.         if (pdef->pixel >= pVisual->ColormapEntries)
  2278.         {
  2279.         clientErrorValue = pdef->pixel;
  2280.             errVal = BadValue;
  2281.         ok = FALSE;
  2282.         }
  2283.         else if (pmap->red[pdef->pixel].refcnt != AllocPrivate)
  2284.         {
  2285.         errVal = BadAccess;
  2286.         ok = FALSE;
  2287.         }
  2288.  
  2289.         /* If this is an o.k. entry, then it gets added to the list
  2290.          * to be sent to the hardware.  If not, skip it.  Once we've
  2291.          * skipped one, we have to copy all the others.
  2292.          */
  2293.         if(ok)
  2294.         {
  2295.         if(idef != n)
  2296.             defs[idef] = defs[n];
  2297.         idef++;
  2298.         }
  2299.         else
  2300.         continue;
  2301.  
  2302.             (*pmap->pScreen->ResolveColor)
  2303.             (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual);
  2304.  
  2305.         pent = &pmap->red[pdef->pixel];
  2306.  
  2307.         if(pdef->flags & DoRed)
  2308.         {
  2309.         if(pent->fShared)
  2310.         {
  2311.             pent->co.shco.red->color = pdef->red;
  2312.             if (pent->co.shco.red->refcnt > 1)
  2313.             ok = FALSE;
  2314.         }
  2315.         else
  2316.             pent->co.local.red = pdef->red;
  2317.         }
  2318.         else
  2319.         {
  2320.         if(pent->fShared)
  2321.             pdef->red = pent->co.shco.red->color;
  2322.         else
  2323.             pdef->red = pent->co.local.red;
  2324.         }
  2325.         if(pdef->flags & DoGreen)
  2326.         {
  2327.         if(pent->fShared)
  2328.         {
  2329.             pent->co.shco.green->color = pdef->green;
  2330.             if (pent->co.shco.green->refcnt > 1)
  2331.             ok = FALSE;
  2332.         }
  2333.         else
  2334.             pent->co.local.green = pdef->green;
  2335.         }
  2336.         else
  2337.         {
  2338.         if(pent->fShared)
  2339.             pdef->green = pent->co.shco.green->color;
  2340.         else
  2341.             pdef->green = pent->co.local.green;
  2342.         }
  2343.         if(pdef->flags & DoBlue)
  2344.         {
  2345.         if(pent->fShared)
  2346.         {
  2347.             pent->co.shco.blue->color = pdef->blue;
  2348.             if (pent->co.shco.blue->refcnt > 1)
  2349.             ok = FALSE;
  2350.         }
  2351.         else
  2352.             pent->co.local.blue = pdef->blue;
  2353.         }
  2354.         else
  2355.         {
  2356.         if(pent->fShared)
  2357.             pdef->blue = pent->co.shco.blue->color;
  2358.         else
  2359.             pdef->blue = pent->co.local.blue;
  2360.         }
  2361.  
  2362.         if(!ok)
  2363.         {
  2364.                 /* have to run through the colormap and change anybody who
  2365.          * shares this value */
  2366.             pred = pent->co.shco.red;
  2367.             pgreen = pent->co.shco.green;
  2368.             pblue = pent->co.shco.blue;
  2369.             ChgRed = pdef->flags & DoRed;
  2370.             ChgGreen = pdef->flags & DoGreen;
  2371.             ChgBlue = pdef->flags & DoBlue;
  2372.             pentLast = pmap->red + pVisual->ColormapEntries;
  2373.  
  2374.             for(pentT = pmap->red; pentT < pentLast; pentT++)
  2375.         {
  2376.             if(pentT->fShared && (pentT != pent))
  2377.             {
  2378.             xColorItem    defChg;
  2379.  
  2380.             /* There are, alas, devices in this world too dumb
  2381.              * to read their own hardware colormaps.  Sick, but
  2382.              * true.  So we're going to be really nice and load
  2383.              * the xColorItem with the proper value for all the
  2384.              * fields.  We will only set the flags for those
  2385.              * fields that actually change.  Smart devices can
  2386.              * arrange to change only those fields.  Dumb devices
  2387.              * can rest assured that we have provided for them,
  2388.              * and can change all three fields */
  2389.  
  2390.             defChg.flags = 0;
  2391.             if(ChgRed && pentT->co.shco.red == pred)
  2392.             {
  2393.                 defChg.flags |= DoRed;
  2394.             }
  2395.             if(ChgGreen && pentT->co.shco.green == pgreen)
  2396.             {
  2397.                 defChg.flags |= DoGreen;
  2398.             }
  2399.             if(ChgBlue && pentT->co.shco.blue == pblue)
  2400.             {
  2401.                 defChg.flags |= DoBlue;
  2402.             }
  2403.             if(defChg.flags != 0)
  2404.             {
  2405.                 defChg.pixel = pentT - pmap->red;
  2406.                 defChg.red = pentT->co.shco.red->color;
  2407.                 defChg.green = pentT->co.shco.green->color;
  2408.                 defChg.blue = pentT->co.shco.blue->color;
  2409.                 (*pmap->pScreen->StoreColors) (pmap, 1, &defChg);
  2410.             }
  2411.             }
  2412.         }
  2413.  
  2414.         }
  2415.     }
  2416.     }
  2417.     /* Note that we use idef, the count of acceptable entries, and not
  2418.      * count, the count of proposed entries */
  2419.     if (idef != 0)
  2420.     ( *pmap->pScreen->StoreColors) (pmap, idef, defs);
  2421.     return (errVal);
  2422. }
  2423.  
  2424. int
  2425. IsMapInstalled(map, pWin)
  2426.     Colormap    map;
  2427.     WindowPtr    pWin;
  2428. {
  2429.     Colormap    *pmaps;
  2430.     int        imap, nummaps, found;
  2431.  
  2432.     pmaps = (Colormap *) ALLOCATE_LOCAL( 
  2433.              pWin->drawable.pScreen->maxInstalledCmaps * sizeof(Colormap));
  2434.     if(!pmaps)
  2435.     return(FALSE);
  2436.     nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps)
  2437.         (pWin->drawable.pScreen, pmaps);
  2438.     found = FALSE;
  2439.     for(imap = 0; imap < nummaps; imap++)
  2440.     {
  2441.     if(pmaps[imap] == map)
  2442.     {
  2443.         found = TRUE;
  2444.         break;
  2445.     }
  2446.     }
  2447.     DEALLOCATE_LOCAL(pmaps);
  2448.     return (found);
  2449. }
  2450.